//  -----------------------------------------------------------------------------------------------//
//   This file is part of SvnExternalUpdater                                                               //
//   Copyright (C)2008 Romain Verdier ( romain@codingly.com )                                      //
//                                                                                                 //
//   This program is free software; you can redistribute it and/or modify it under the terms       //
//   of the GNU General Public License as published by the Free Software Foundation; either        //
//   version 2 of the License, or (at your option) any later version. This program is distributed  //
//   in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied        //
//   warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public  //
//   License for more details.                                                                     //
//                                                                                                 //
//   You should have received a copy of the GNU General Public License along with this program; if //
//   not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. or  //
//   see http://www.fsf.org/licensing/licenses/gpl.html                                            //
//  -----------------------------------------------------------------------------------------------//
using System;
using Codingly.SvnExternalUpdater.Core.EventHandlers;
using Codingly.SvnExternalUpdater.Core.Model;

namespace Codingly.SvnExternalUpdater.Core
{
    internal class External : IExternal, IRemoteConnected
    {
        private readonly string id;
        private readonly IRemoteFolder remoteFolder;

        private string path;

        public External(IRemoteFolder folder, IProject project)
        {
            remoteFolder = folder;
            Project = project;
            id = Guid.NewGuid().ToString();
        }

        public Uri AbsoluteUrl
        {
            get { return remoteFolder.Url; }
        }

        public string ProjectName { get; private set; }

        public ExternalType Type { get; set; }

        internal IProject Project { get; private set; }

        internal IRemoteFolder RemoteFolder
        {
            get { return remoteFolder; }
        }

        #region IExternal Members

        public long LocalRevision { get; internal set; }
        public bool HasRevision { get; internal set; }

        public event ExternalEventHandler Changed = delegate { };

        public string Path
        {
            get { return path; }
            internal set
            {
                path = value;
                ProjectName = ExtractProjectName(value);
            }
        }

        public string Definition
        {
            get
            {
                switch (Type)
                {
                    case ExternalType.FolderFirst:
                        return string.Format("{0} -r{1} {2}", path, LocalRevision, this.RelativeUrl);
                    case ExternalType.FolderFirstWithoutRevision:
                        return string.Format("{0} {1}", path, this.RelativeUrl);
                    case ExternalType.RevisionFirst:
                        return string.Format("-r{0} {1} {2}", LocalRevision, this.RelativeUrl, path);
                    case ExternalType.UrlFirst:
                        return string.Format("{0} {1}", this.RelativeUrl, path);
                    case ExternalType.UrlFirstWithRevision:
                        return string.Format("{0}@{1} {2}", this.RelativeUrl, LocalRevision, path);
                    default:
                        return string.Empty;
                }
            }
        }

        public string RelativeUrl { get; internal set; }

        public long RemoteRevision
        {
            get { return remoteFolder.Revision; }
        }

        public Uri Url
        {
            get { return remoteFolder.Url; }
        }

        public bool IsUpToDate
        {
            get { return !HasRevision || LocalRevision >= remoteFolder.Revision; }
        }

        #endregion

        #region IRemoteConnected Members

        string IRemoteConnected.Id
        {
            get { return id; }
        }

        IRemoteFolder IRemoteConnected.RemoteFolder
        {
            get { return RemoteFolder; }
        }

        #endregion

        public void UpdateLocalRevision()
        {
            LocalRevision = remoteFolder.Revision;
        }

        internal void FireChanged()
        {
            Changed(this, new ExternalEventArgs(this));
        }

        private static string ExtractProjectName(string url)
        {
            string[] urlParts = url.Split('/');
            if (urlParts.Length >= 2)
            {
                return string.Format("{0}/{1}", urlParts[urlParts.Length - 2], urlParts[urlParts.Length - 1]);
            }
            return url;
        }
    }
}